local jass = require 'jass.common'
local japi = require 'jass.japi'
local msg  = require 'jass.message'

local mover = { }
setmetatable(mover,mover)
ac.mover.class['bezier'] = mover

local mt = { }
mover.__index = mt 
extends(ac.mover)(mt)

-- 起始点
mt.start = nil 

-- 目标点
mt.target = nil

-- 中继点
mt.center = nil

-- 速度
mt.speed = 1000

-- 是否旋转倾角
mt.pitch_flag = true 

-- 偏差超过一定直接直线运动
mt.lock_range = 500 

-- 体积
mt.collision = 0

function mt:init()
    ac.mover.__index.init(self)
    if not self.start then 
        log.error('没有传入起始点')
        return
    end 
    if not self.center then 
        log.error('没有传入参照点')
        return
    end 
    if not self.target then 
        log.error('没有传入目标点')
        return
    --elseif self.target.type ~= 'point' then 
    --    log.error('传入目标不是一个点')
    --    return
    end 
    self.target_point = self.target:get_point()
    if self.target.type=='unit' then
        self.target_point = self.target:get_impact_point()
    end
    self.length = math.sqrt((self.start.z - self.center.z + self.collision) ^ 2 + (self.start * self.center) ^ 2) + math.sqrt((self.center.z - self.target_point.z + self.collision) ^ 2 + (self.center * self.target_point) ^ 2)
    self.moved = 0
    self.mover:set_point(self.start)
    self.mover:set_height(self.start.z)
end

-- 移动
function mt:move()
    local start = self.start 
    local center = self.center
    local target = self.target_point
    local start_height = self.start.z 
    local center_height = self.center.z 
    local target_height = self.target.z 
    local length = self.length
    local speed = self.speed 
    local object = self.mover
    if length == 0 then
        self:finish()
        return
    end 
    if speed < 0 then 
        self.moved = length
    else
        if speed == 0 then 
            speed = length
        end
        self.moved = self.moved + speed * self.frame
    end 
    local progress = math.min(self.moved / self.length, 1)
    local cpoint1 = start:lerp( center, progress)
    local cpoint2 = center:lerp( target, progress)
    local cheight1 = math.lerp(start.z, center.z, progress)
    local cheight2 = math.lerp(center.z, target.z, progress)
    local point = cpoint1:lerp( cpoint2, progress)
    local height = math.lerp(cheight1, cheight2, progress)
    local angle = cpoint1 / cpoint2
    local pitch =  ( (progress < 1) and self.pitch_flag) and math.atan( cheight1 - cheight2, math.sqrt( (cpoint1.x - cpoint2.x) ^ 2 + (cpoint1.y - cpoint2.y) ^ 2 ) ) or 0
    if object.type == 'unit' then 
        height = height - point:get_height()
    end 
    self.angle = angle
    self.last_speed = (point * object:get_point()) / self.frame
    if self:notify ('on_move', point, height) == false then 
        self:finish()
        return  
    end 
    self:set_point(point)
    self:set_height(height)
    self:set_rotate(0, pitch, angle)
    if progress == 1 then 
        self:finish()
    elseif self.target.type=='unit' and self.lock_range>0 then
        local point1 = self.target:get_impact_point()
        local range = point1*target
        if range<self.lock_range then
            self.lock_range = self.lock_range - range
            self.target_point = point1
            self.length = math.sqrt((self.start.z - self.center.z + self.collision) ^ 2 + (self.start * self.center) ^ 2) + math.sqrt((self.center.z - self.target_point.z + self.collision) ^ 2 + (self.center * self.target_point) ^ 2)
        else
            self.lock_range = 0
            self.start = point
            local class = ac.mover.class.target
            local mt = setmetatable(self,ac.mover.class.target)
            mt:init(true)
        end
    end 
end 

return mover